package de.codi.mappingevaluation;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLOntology;

import de.codi.exception.CodiException;
import de.codi.read.StoredOntology;
import de.codi.string.StringPreparation;

public class ReadOntology {

	private static StoredOntology ontology;
	public Map<String, Set<String>> info;
	public Set<OWLEntity> entities = new HashSet<OWLEntity>();

	public ReadOntology(String path) throws CodiException {
		try {
		    ontology = new StoredOntology(new URI(path));
        } catch(URISyntaxException e) {
            e.printStackTrace();
        }
		OWLOntology ont = ontology.ont;

		HashMap<String, String> map = new HashMap<String, String>();
		Pattern result = Pattern.compile("http://([^#].*owl#[^ ].*)");
		Matcher m;
		
		for (OWLAxiom ax : ont.getAxioms()) {
			if (ax instanceof OWLAnnotationAssertionAxiom) {
					OWLAnnotationAssertionAxiom aax = (OWLAnnotationAssertionAxiom) ax;

					OWLAnnotation a = aax.getAnnotation();
					m = result.matcher(aax.getSubject().toString());
					m.find();
					String key = m.group(1);

					if (a.getValue() instanceof OWLLiteral) {
						OWLLiteral val = (OWLLiteral) a.getValue();
						map.put(key, val.getLiteral());
					}
				}
			}

		entities.addAll(ont.getClassesInSignature());
		entities.addAll(ont.getDataPropertiesInSignature());
		entities.addAll(ont.getObjectPropertiesInSignature());

		info = new HashMap<String, Set<String>>();
		for (OWLEntity ent : entities) {
			Set<String> pool = new HashSet<String>();
			pool.add(StringPreparation.standardize(ent.getIRI().getFragment()));
			Set<OWLAnnotation> annotations = ent.getAnnotations(ont);
//			System.out.println("\n" + ent.getIRI().toString() + ": " + annotations.size());
			String key = ent.getIRI().toString();
			for (OWLAnnotation an : annotations) {
				if (an.getValue() instanceof OWLLiteral) {
					OWLLiteral val = (OWLLiteral) an.getValue();
//					 System.out.println("\t-> " + val.getLiteral());
					pool.add(StringPreparation.standardize(val.getLiteral()));
				} else {
					m = result.matcher(an.getValue().toString());
					m.find();
					String info = map.get(m.group(1));
					info = StringPreparation.standardize(info);
//					System.out.println("\t-> " + info);
					pool.add(info);
				}
			}
			// System.out.println("\t-> " + pool.toString());
			info.put(key, removeShortCut(pool));
		}
	}
	

    private Set<String> removeShortCut(Set<String> values)
    {
        List<String> tmp = new ArrayList<String>(values);
        
        for(int i = 0; i < values.size(); i++) {
            for(int j = 0; j < values.size(); j++) {
            	if (i != j){
	            	List<String> tmp_r = StringPreparation.shortCut(tmp.get(i), tmp.get(j));
	                if(tmp_r.get(0).equals(tmp_r.get(1)) && tmp.get(i).length()<tmp.get(j).length()) { values.remove(tmp.get(i)); continue; }
	                if(tmp_r.get(0).equals(tmp_r.get(1)) && tmp.get(j).length()<tmp.get(i).length()) { values.remove(tmp.get(j)); continue; }
	                // part2:
	                String shortString[] = null, longString[]=null;
	                int shortID = -1;
                
                	if (tmp.get(i).length() != tmp.get(j).length()){
	                	if (tmp.get(i).length() < tmp.get(j).length()){
	                		shortString = tmp.get(i).split(" ");
	                		longString = tmp.get(j).split(" ");
	                		shortID = i;
	                	} else {
	                		shortString = tmp.get(j).split(" ");
	                		longString = tmp.get(i).split(" ");
	                		shortID = j;
	                	}
	                	if (Math.abs(shortString.length - longString.length) > 2)
	                		continue;
	                	Set<Integer> check = new HashSet<Integer>();
	                	for(int k = 0; k <shortString.length; k++){
	                		if (shortString[k].length() > 1) continue;
	                		for(int l = 0; l <longString.length; l++){
	                			if (!check.contains(l) && (longString[l].startsWith(shortString[k]) || longString[l].equals(shortString[k]))){
	                				check.add(l);
	                			}
	                		}
	                	}
	                	if (check.size() >= shortString.length){
//	                		System.out.println(tmp.get(i) + " -  "+ tmp.get(j) + "\n\t"+ tmp.get(shortID));
	                		values.remove(tmp.get(shortID));
//	                		System.out.println(values.contains(tmp.get(shortID)));
	                	}
                	}
                }
            }
        }

        return values;
    }

}